#include "king.h"
#include "src/move.h"
#include "src/constants.h"

King::King( int x, int y, QString pixmap_path, int color, QGraphicsItem* parent ) : BoardFigure( x, y, pixmap_path, color, parent )
{
}

QList<Move*>& King::getPossibleMoves( BoardFigure* board[8][8] ) {
  qDebug() << "King GetPossibleMoves called";

  if ( possibleMovesReady ) return possibleMoves;

  int dx[] = { 0, 1, 1,  1,  0, -1, -1, -1 };
  int dy[] = { 1, 1, 0, -1, -1, -1,  0,  1 };
  int oppositeColor = ( getColor() == Constants::COLOR_BLACK ) ? ( Constants::COLOR_WHITE ) : ( Constants::COLOR_BLACK );
  qDebug() << "Color: " << getColor() << " Opposite color:" << oppositeColor;
  for ( int i=0; i < 8; i++ ) {
    int newX = getBoardX() + dx[i];
    int newY = getBoardY() + dy[i];
    if ( checkNewPos( newX, newY )
         && ( board[newX][newY] == 0 || board[newX][newY]->getColor() != getColor() )
         && !isFieldUnderAttackByColor( newX, newY, oppositeColor, board )
       ) {
      // TODO: check every field for capturing
      Move* move = new Move( getBoardX(), getBoardY(), newX, newY );
      possibleMoves.push_back( move );
    }
  }

  qDebug() << "Shortcastling checks begin";
  // King castling
  if ( isShortCastlingPossible( board ) ) {
    int shortCastlingDx = 2;
    int rockX = Constants::BOARD_SIZE-1;
    int rockY = ( getColor() == Constants::COLOR_WHITE ) ? ( 0 ) : ( Constants::BOARD_SIZE-1 );

    int newX = getBoardX() + shortCastlingDx;
    int newY = getBoardY();
    int newRockX = newX - 1;
    int newRockY = newY;

    qDebug() << "Making shortCastling move";
    Move* shortCastling = new Move( getBoardX(), getBoardY(),
                                    newX, newY,
                                    rockX, rockY,
                                    newRockX, newRockY );
    possibleMoves.push_back(shortCastling);
  }
  qDebug() << "Shortcastling checks ends";

  qDebug() << "Longcastling checks begin";
  // Queen castling
  if ( isLongCastlingPossible( board ) ) {
    int longCastlingDx = -2;
    int rockX = 0;
    int rockY = ( getColor() == Constants::COLOR_WHITE ) ? ( 0 ) : ( Constants::BOARD_SIZE-1 );

    int newX = getBoardX() + longCastlingDx;
    int newY = getBoardY();
    int newRockX = newX + 1;
    int newRockY = newY;

    qDebug() << "Making longCastling move";
    Move* longCastling = new Move( getBoardX(), getBoardY(),
                                   newX, newY,
                                   rockX, rockY,
                                   newRockX, newRockY );
    possibleMoves.push_back(longCastling);
  }
  qDebug() << "Longcastling checks ends";

  possibleMovesReady = true;
  return possibleMoves;
}

QList<QPoint*>& King::getAttackedFields( BoardFigure* board[8][8] )
{
  if ( attackedFieldsReady ) return attackedFields;

  int dx[] = { 0, 1, 1,  1,  0, -1, -1, -1 };
  int dy[] = { 1, 1, 0, -1, -1, -1,  0,  1 };
  for ( int i=0; i < 8; i++ ) {
    int newX = getBoardX() + dx[i];
    int newY = getBoardY() + dy[i];

    QPoint* field = new QPoint( newX, newY );
    attackedFields.push_back( field );
  }

  attackedFieldsReady = true;
  return attackedFields;
}

bool King::isShortCastlingPossible( BoardFigure* board[8][8] )
{
  int color = getColor();
  int oppositeColor = ( color == Constants::COLOR_BLACK ) ? ( Constants::COLOR_WHITE ) : ( Constants::COLOR_BLACK );
  bool result = true;

  // Check that king doesn't move before
  if ( getMoveCount() > 0 ) {
    result = false;
    return result;
  }

  // Find rock
  int rockX = Constants::BOARD_SIZE-1;
  int rockY = ( color == Constants::COLOR_WHITE ) ? ( 0 ) : ( Constants::BOARD_SIZE-1 );
  BoardFigure* rock = board[rockX][rockY];
  if ( rock == 0 ) {
    result = false;
    return result;
  }

  // Check rock doesn't move
  if ( rock->getMoveCount() > 0 ) {
    result = false;
    return result;
  }

  // Check there is no figures between rock and king
  int currentX = rockX - 1;
  while ( currentX != getBoardX() )
    {
      if ( board[currentX][rockY] != 0 ) {
        result = false;
        break;
      }
      --currentX;
    }

  if ( !result ) return result;

  // Check that king is not under attack
  // and doesn't cross attacked fields
  for( int i = getBoardX(); i <= getBoardX() + 2; i++ ) {
    int x = i;
    int y = getBoardY();
    if ( isFieldUnderAttackByColor( x, y, oppositeColor, board ) ) {
      result = false;
      break;
    }
  }
  if ( !result ) return result;

  return result;
}

bool King::isLongCastlingPossible( BoardFigure* board[8][8] )
{
  int color = getColor();
  int oppositeColor = ( color == Constants::COLOR_BLACK ) ? ( Constants::COLOR_WHITE ) : ( Constants::COLOR_BLACK );
  qDebug() << "Current color: " << color << " OppositeColor: " << oppositeColor; 
  bool result = true;

  // Check that king doesn't move before
  if ( getMoveCount() > 0 ) {
    result = false;
    return result;
  }

  // Find rock
  int rockX = 0;
  int rockY = ( color == Constants::COLOR_WHITE ) ? ( 0 ) : ( Constants::BOARD_SIZE-1 );
  BoardFigure* rock = board[rockX][rockY];
  if ( rock == 0 ) {
    result = false;
    return result;
  }

  // Check rock doesn't move
  if ( rock->getMoveCount() > 0 ) {
    result = false;
    return result;
  }

  // Check there is no figures between rock and king
  int currentX = rockX + 1;
  while ( currentX != getBoardX() )
    {
      if ( board[currentX][rockY] != 0 ) {
        result = false;
        break;
      }
      ++currentX;
    }

  if ( !result ) return result;

  // Check that king is not under attack
  // and doesn't cross attacked fields
  for( int i = getBoardX(); i >= getBoardX() - 2; i-- ) {
    int x = i;
    int y = getBoardY();
    if ( isFieldUnderAttackByColor( x, y, oppositeColor, board ) ) {
      result = false;
      break;
    }
  }
  if ( !result ) return result;

  return result;
}

